<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
<meta name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">

    <meta name="author" content="Ian Tang">


    <meta name="subtitle" content="岁月不居时节如流">


    <meta name="description" content="好记性不如烂笔头">



<title>鸟哥的私房菜 | 随笔</title>



    <link rel="icon" href="/image/The_Lion_King_32_32.png">




    <!-- stylesheets list from _config.yml -->
    
    <link rel="stylesheet" href="/css/style.css">
    



    <!-- scripts list from _config.yml -->
    
    <script src="/js/script.js"></script>
    
    <script src="/js/tocbot.min.js"></script>
    



    
    
        
    


<meta name="generator" content="Hexo 6.3.0"></head>

<body>
    <script>
        // this function is used to check current theme before page loaded.
        (() => {
            const currentTheme = window.localStorage && window.localStorage.getItem('theme') || '';
            const isDark = currentTheme === 'dark';
            const pagebody = document.getElementsByTagName('body')[0]
            if (isDark) {
                pagebody.classList.add('dark-theme');
                // mobile
                document.getElementById("mobile-toggle-theme").innerText = "· Dark"
            } else {
                pagebody.classList.remove('dark-theme');
                // mobile
                document.getElementById("mobile-toggle-theme").innerText = "· Light"
            }
        })();
    </script>

    <div class="wrapper">
        <header>
    <nav class="navbar">
        <div class="container">
            <div class="navbar-header header-logo"><a href="/">Tangkaifei&#39;s Blog</a></div>
            <div class="menu navbar-right">
                
                    <a class="menu-item" href="/archives">Posts</a>
                
                    <a class="menu-item" href="/category">Categories</a>
                
                    <a class="menu-item" href="/tag">Tags</a>
                
                    <a class="menu-item" href="/about">About</a>
                
                <input id="switch_default" type="checkbox" class="switch_default">
                <label for="switch_default" class="toggleBtn"></label>
            </div>
        </div>
    </nav>

    
    <nav class="navbar-mobile" id="nav-mobile">
        <div class="container">
            <div class="navbar-header">
                <div>
                    <a href="/">Tangkaifei&#39;s Blog</a><a id="mobile-toggle-theme">·&nbsp;Light</a>
                </div>
                <div class="menu-toggle" onclick="mobileBtn()">&#9776; Menu</div>
            </div>
            <div class="menu" id="mobile-menu">
                
                    <a class="menu-item" href="/archives">Posts</a>
                
                    <a class="menu-item" href="/category">Categories</a>
                
                    <a class="menu-item" href="/tag">Tags</a>
                
                    <a class="menu-item" href="/about">About</a>
                
            </div>
        </div>
    </nav>

</header>
<script>
    var mobileBtn = function f() {
        var toggleMenu = document.getElementsByClassName("menu-toggle")[0];
        var mobileMenu = document.getElementById("mobile-menu");
        if(toggleMenu.classList.contains("active")){
           toggleMenu.classList.remove("active")
            mobileMenu.classList.remove("active")
        }else{
            toggleMenu.classList.add("active")
            mobileMenu.classList.add("active")
        }
    }
</script>
            <div class="main">
                <div class="container">
    
    
        <div class="post-toc">
    <div class="tocbot-list">
    </div>
    <div class="tocbot-list-menu">
        <a class="tocbot-toc-expand" onclick="expand_toc()">Expand all</a>
        <a onclick="go_top()">Back to top</a>
        <a onclick="go_bottom()">Go to bottom</a>
    </div>
</div>

<script>
    var tocbot_timer;
    var DEPTH_MAX = 6; // 为 6 时展开所有
    var tocbot_default_config = {
        tocSelector: '.tocbot-list',
        contentSelector: '.post-content',
        headingSelector: 'h1, h2, h3, h4, h5',
        orderedList: false,
        scrollSmooth: true,
        onClick: extend_click,
    };

    function extend_click() {
        clearTimeout(tocbot_timer);
        tocbot_timer = setTimeout(function() {
            tocbot.refresh(obj_merge(tocbot_default_config, {
                hasInnerContainers: true
            }));
        }, 420); // 这个值是由 tocbot 源码里定义的 scrollSmoothDuration 得来的
    }

    document.ready(function() {
        tocbot.init(obj_merge(tocbot_default_config, {
            collapseDepth: 1
        }));
    });

    function expand_toc() {
        var b = document.querySelector('.tocbot-toc-expand');
        var expanded = b.getAttribute('data-expanded');
        expanded ? b.removeAttribute('data-expanded') : b.setAttribute('data-expanded', true);
        tocbot.refresh(obj_merge(tocbot_default_config, {
            collapseDepth: expanded ? 1 : DEPTH_MAX
        }));
        b.innerText = expanded ? 'Expand all' : 'Collapse all';
    }

    function go_top() {
        window.scrollTo(0, 0);
    }

    function go_bottom() {
        window.scrollTo(0, document.body.scrollHeight);
    }

    function obj_merge(target, source) {
        for (var item in source) {
            if (source.hasOwnProperty(item)) {
                target[item] = source[item];
            }
        }
        return target;
    }
</script>
    

    
    <article class="post-wrap">
        <header class="post-header">
            <h1 class="post-title">鸟哥的私房菜</h1>
            
                <div class="post-meta">
                    
                        Author: <a itemprop="author" rel="author" href="/">Ian Tang</a>
                    

                    
                        <span class="post-time">
                        Date: <a href="#">十一月 27, 2022&nbsp;&nbsp;11:56:00</a>
                        </span>
                    
                    
                        <span class="post-category">
                    Category:
                            
                                <a href="/categories/%E6%8A%80%E6%9C%AF%EF%BC%9A%E7%9F%A5%E8%AF%86%E6%8A%80%E8%83%BD/">技术：知识技能</a>
                            
                        </span>
                    
                </div>
            
        </header>

        <div class="post-content">
            <h1 id="第19章-启动流程、模块管理与Loader"><a href="#第19章-启动流程、模块管理与Loader" class="headerlink" title="第19章 启动流程、模块管理与Loader"></a>第19章 启动流程、模块管理与Loader</h1><p>按下电源&gt;&gt;计算机硬件寻找BIOS或者UEFI BIOS来加载硬件信息&gt;&gt;系统主动读取BIOS里设置的第一个可启动的设备&gt;&gt;启动引导程序</p>
<p>启动引导程序决定选择哪一个内核文件启动&gt;&gt;加载该内核文件到内存中解压缩与执行&gt;&gt;内核在内存中检测硬件及加载硬件驱动程序&gt;&gt;操作系统运行</p>
<h2 id="BIOS、boot-loader、kernel加载"><a href="#BIOS、boot-loader、kernel加载" class="headerlink" title="BIOS、boot loader、kernel加载"></a>BIOS、boot loader、kernel加载</h2><p>我们要想启用一个操作系统，必须先要加载BIOS（basic input output system），通过BIOS去加载CMOS的信息，借由CMOS的设置取得各种硬件配置。</p>
<p>取得这些信息后，BIOS进行自检，接着读取启动设备中的引导信息。</p>
<p>BIOS设置读取的设备先后顺序，读取第一个设备的内核信息，因为不同操作系统的文件系统格式不一样，因此需要一个启动引导程序处理内核文件的加载load，这个启动引导程序就是boot loader，它安装在读取设备的第一个扇区内，也就是MBR(Master boot record)。</p>
<blockquote>
<p>boot loader 不相同，BIOS又是怎么读取MBR内的boot的？</p>
<p><strong>BIOS通过硬件的INT13中断功能来读取MBR，只要BIOS能检测到硬盘就可以通过INT 13读取</strong></p>
</blockquote>
<p><strong>多重加载</strong></p>
<p>既然每一个系统都需要boot loader引导安装不同系统的内核文件到内存中解压缩和执行，不同系统的boot loader又是不相同的，那么双系统的电脑就必须有两个不一样的boot，而boot放在MBR中，也就是磁盘的第一个sector内，两个boot怎么放？</p>
<p>实际上每个文件系统都会保留一个启动扇区boot sector用来供操作系统安装boot loader，通常默认操作系统都会安装loader到boot sector上。windows操作系统默认主动将boot loader安装到MBR和boot sector上，而linux操作系统可以选择将boot loader安装到boot sector上，也可以不安装，所以装双系统的话，MBR上通常都会有多个不同操作系统的boot loader覆盖。</p>
<p>怎么解决以上两个问题？</p>
<blockquote>
<p>boot loader提供三个功能：</p>
<ol>
<li>提供选项：用户可以选择不同的启动选项，这也是多重引导的功能</li>
<li>加载内核文件：直接指向启动的程序区域来启动系统</li>
<li>转交其他loader：将启动管理功能转交给其他的loader</li>
</ol>
</blockquote>
<p>由于具有提供选项功能，我们可以选择不同的内核来启动；有转交其他loader功能，我们可以加载其他boot sector的loader。不过windows的loader默认不具有转交功能，因此不能通过windows的loader转交到其他系统的loader。</p>
<p>一般都是先装windows后装Linux，MBR采用Linux的grub2这个boot loader：</p>
<ul>
<li>grub2 – kernel file – booting</li>
<li>grub2 – boot sector（windows） – windows kernel file  – booting</li>
<li>grub2 – bootsector （grub2）–kernel file – booting</li>
</ul>
<p>内核会自己检测一遍硬件信息，内核放在&#x2F;boot&#x2F;vmlinuz</p>
<p>Linux内核会将非必要的功能编译成模块放在&#x2F;lib&#x2F;modules内，它与根目录&#x2F; 必须放在同一个硬盘分区，启动后会挂载根目录&#x2F; 这样就可以读取到modules内的模块</p>
<p>一般来说usb、sata、scsi等磁盘设备的驱动都被编译成模块</p>
<p>正常流程：开机通过BIOS的INT 13获取到boot loader引导加载内核并挂载根目录，问题是磁盘的驱动文件在&#x2F;lib&#x2F;modules内，没有驱动挂载不了根目录。通过虚拟文件解决这个问题。&#x2F;boot&#x2F;initrd或者&#x2F;boot&#x2F;initramfs，这个文件可以通过boot loader加载到内存中（内核在&#x2F;boot&#x2F;vmlinuz），解压缩并在内存中模拟成一个根目录，提供一个可执行的文件，这个可执行文件可以加载启动需要的内核模块，也就是不挂载根目录就可以使用内核分离出来的各个模块功能，等加载完成会帮助内核重新调用systemd开始正常启动流程。</p>
<p>systemd启动之后就开始起用&#x2F;etc&#x2F;systemd&#x2F;system&#x2F;default.target接下来链接到&#x2F;usr&#x2F;lib&#x2F;systemd&#x2F;system&#x2F;multi-user.target或者graphical.target其中一个，接下来可以十八章的systemd的一些内容</p>
<h2 id="内核与内核模块"><a href="#内核与内核模块" class="headerlink" title="内核与内核模块"></a>内核与内核模块</h2><p>在整个启动过程中，成功的驱动硬件设备是内核的工作，内核一般都是压缩文件，在使用内核之前需要解压缩，现在的内核都是可读取模块化驱动程序，内核与内核模块放置位置：</p>
<ul>
<li>内核：&#x2F;boot&#x2F;vmlinuz</li>
<li>内核解压缩：&#x2F;boot&#x2F;initamfs</li>
<li>内核模块&#x2F;lib&#x2F;modules&#x2F;version&#x2F;kernel</li>
<li>内核版本：&#x2F;proc&#x2F;version</li>
</ul>
<p>所以如果加入一个新的硬件，操作系统不支持有两种方法解决：</p>
<ul>
<li>重新编译内核，加入该硬件的驱动程序</li>
<li>将该硬件的驱动编译成模块&#x2F;lib&#x2F;modules，在启动时加载该模块</li>
</ul>
<h3 id="内核模块与依赖性"><a href="#内核模块与依赖性" class="headerlink" title="内核模块与依赖性"></a>内核模块与依赖性</h3><p>在&#x2F;lib&#x2F;modules&#x2F;$(uname -r)&#x2F;modules.dep文件里记录了内核支持的模块的各项依赖性</p>
<p>内核模块都是.ko结尾的文件</p>
<p>如果新加入一个网络硬件模块</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cp example.ko /lib/modules/$(uname -r)/kernel/drivers/net</span><br><span class="line">depmod -a</span><br></pre></td></tr></table></figure>

<p>depmod命令可以扫描模块文件信息重新生成modules.dep文件</p>
<p>lsmod可以查看加载了多少模块</p>
<p>modprobe会主动查找modules.dep里的内容，解决模块依赖性之后加载模块，删除是modprobe -r</p>
<h1 id="第21章-软件安装：源代码与Tarball"><a href="#第21章-软件安装：源代码与Tarball" class="headerlink" title="第21章 软件安装：源代码与Tarball"></a>第21章 软件安装：源代码与Tarball</h1><h2 id="开放源码、编译器、可执行文件"><a href="#开放源码、编译器、可执行文件" class="headerlink" title="开放源码、编译器、可执行文件"></a>开放源码、编译器、可执行文件</h2><p>Linux可执行文件操作起来是看是否有+x的权限，但是这也是调用bash这个程序的功能进行一些判断，Linux上真正的可执行文件是二进制程序。</p>
<p>既然真正的可执行文件是二进制程序，怎么制作这样一个二进制程序呢？</p>
<p>首先，写程序，就是源代码，一般就是一个纯文本文件。其次将写完的源代码文件进行编译，编译成操作系统看的懂的二进制程序，编译需要编译器。</p>
<p>例如c是Linux上最标准的程序语言，使用c进行编写，写完后用gcc这个编译器进行编译，就可以制作一个可以执行的二进制程序。</p>
<p>在编译的过程中还会产生所谓的目标文件（object file），这个文件是以.o的扩展名样式存在。有的时候我们会在程序中引用其他的外部子程序，或者利用其他软件的函数功能，这个时候我们必须在编译的过程中将该函数库加进去，如此一来，编译器就可以将所有的程序代码与函数库作一个链接（link）以产生正确的执行文件。</p>
<h2 id="函数库"><a href="#函数库" class="headerlink" title="函数库"></a>函数库</h2><p>函数库包括静态函数库与动态函数库</p>
<p>一般放在&#x2F;usr&#x2F;include、&#x2F;usr&#x2F;lib、&#x2F;usr&#x2F;lib64</p>
<p>函数库就是类似子程序的角色</p>
<h2 id="make、configure"><a href="#make、configure" class="headerlink" title="make、configure"></a>make、configure</h2><p>使用gcc类似的编译器去编译一两个开源源码还好，有些应用程序包含一堆程序代码，每个主程序和子程序都要写上一句编译命令，还有外部函数库的链接，工作量就会巨大，这时候可以使用make这个命令的相关功能进行编译的简化。</p>
<p>当执行make时，会在当前目录内寻找makefile（Makefile）这个文本文件，而makefile里面记录了源代码如何编译的详细信息。make会自动判别源代码是否经过变动。</p>
<p>通常软件开发商会写一个检测程序来检测用户的操作环境，以及该操作环境是否有软件开发商所需要的其他功能，该检测程序检测完毕会主动建立这个Makefile的规格文件，通常这个检测程序的文件名为configure或者config。</p>
<p>一般的检测内容如下：</p>
<ul>
<li>是否有合适的编译器可以编译本软件的程序代码</li>
<li>是否已经存在本软件需要的函数库或其他依赖文件</li>
<li>操作系统平台是否适合本软件，包括linux内核版本</li>
<li>内核的头文件（header include）是否存在（驱动程序必要的检测）</li>
</ul>
<h2 id="使用C进行编译实例"><a href="#使用C进行编译实例" class="headerlink" title="使用C进行编译实例"></a>使用C进行编译实例</h2><p>预先安装gcc和make软件</p>
<p>编辑源代码：hello.c</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"># <span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">(<span class="type">void</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;hello,world&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>编译源代码：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gcc hello.c</span><br></pre></td></tr></table></figure>

<p>如果使用gcc编译器，没有使用任何参数，则执行文件的文件名被设置为a.out</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">gcc -c hello.c #产生目标文件 hello.o</span><br><span class="line">gcc -o hello hello.o #通过目标文件生成执行文件hello</span><br></pre></td></tr></table></figure>

<p>为什么要生成目标文件.o，直接执行a.out不一样么？</p>
<p>当在主程序里调用子程序时，就需要编译多个源代码，但是执行文件只有一个，这时候就需要先产生目标文件，再以链接制作成为二进制可执行文件</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">gcc -c a.c b.c #编译目标文件</span><br><span class="line">gcc -o test a.o b.o</span><br><span class="line">./test</span><br></pre></td></tr></table></figure>

<p>另外如果更新b.c的内容，只要重新编译b.c的内容，重新生成目标文件b.o再次编译制作新的二进制文件就行</p>
<h2 id="使用make进行宏编译"><a href="#使用make进行宏编译" class="headerlink" title="使用make进行宏编译"></a>使用make进行宏编译</h2><p>简化编译过程</p>
<p>编写Makefile：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">main:main.o aaa.o bbb.o ccc.o</span><br><span class="line">	gcc -o main main.o aa.o bbb.o ccc.o</span><br></pre></td></tr></table></figure>

<p>make主动判断每个目标文件相关的源代码并直接编译，最后在进行链接</p>
<p>Makefile语法：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">目标（target）： 目标文件1 目标文件2 </span><br><span class="line">&lt;tab&gt;  gcc -c 建立的二进制执行文件 目标文件1 目标文件2</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">example</span></span><br><span class="line">main :main.o a.o</span><br><span class="line">	gcc -o main main.o a.o</span><br><span class="line">clean :main.o a.o</span><br><span class="line">	rm -f main.o a.o</span><br></pre></td></tr></table></figure>

<p>可以执行make clean&#x2F;make main&#x2F;make clean main这些命令</p>
<p>静态函数库 .a结尾</p>
<p>动态函数库.so结尾</p>
<p>可以把动态函数库加载进内存</p>
<p>ldd查看可执行的二进制文件依赖的函数库</p>
<h1 id="第24章-Linux内核编译与管理"><a href="#第24章-Linux内核编译与管理" class="headerlink" title="第24章 Linux内核编译与管理"></a>第24章 Linux内核编译与管理</h1><p>内核就是系统上面的一个文件而已，这个文件包含了驱动各个硬件的检测程序和驱动模块。</p>
<p>内核放在&#x2F;boot&#x2F;vmlinuz-xxx</p>
<p>内核模块放在&#x2F;lib&#x2F;modules&#x2F;$(uname -r)&#x2F;kernel</p>
<p>内核是通过源代码编译而成</p>
<h2 id="内核编译前的预处理与内核功能选择"><a href="#内核编译前的预处理与内核功能选择" class="headerlink" title="内核编译前的预处理与内核功能选择"></a>内核编译前的预处理与内核功能选择</h2><p>内核是起到管理硬件与提供系统内核功能，因此需要先预处理找到系统硬件，规划内核用途。</p>
<h3 id="硬件查看"><a href="#硬件查看" class="headerlink" title="硬件查看"></a>硬件查看</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cat /proc/cpuinfo</span><br><span class="line"></span><br><span class="line">lspci</span><br></pre></td></tr></table></figure>

<h3 id="保持干净源代码：make-mrproper"><a href="#保持干净源代码：make-mrproper" class="headerlink" title="保持干净源代码：make mrproper"></a>保持干净源代码：make mrproper</h3><p>先下载源代码，可以在国内找镜像站下载最新的稳定版内核源代码，或者Linux发行方提供的内核源代码</p>
<p>我们需要处理一下内核源代码下面的残留文件。我们不清楚下载下来的源代码中有没有保留目标文件（*.o）以及相关的配置文件</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd /usr/src/kernel/linux-3.10.89</span><br><span class="line">make mrproper</span><br></pre></td></tr></table></figure>

<p>这个操作会将之间进行过的内核功能选择文件也删除，所以只有第一次执行内核编译才进行，其余时刻想要删除前一次编译的残留，只要执行</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make clean</span><br></pre></td></tr></table></figure>

<p>make clean仅会删除类似目标文件之类的编译过程产生的中间件，<strong>不会删除配置文件</strong></p>
<h3 id="开始选择内核功能：make-XXconfig"><a href="#开始选择内核功能：make-XXconfig" class="headerlink" title="开始选择内核功能：make XXconfig"></a>开始选择内核功能：make XXconfig</h3><p>在&#x2F;boot下面存在一个config-XXX的文件，是功能列表，有很多方法建立这个文件，生成一个.config的配置文件</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make menuconfig</span><br></pre></td></tr></table></figure>

<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make oldconfig</span><br></pre></td></tr></table></figure>

<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make xconfig</span><br></pre></td></tr></table></figure>

<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make gconfig</span><br></pre></td></tr></table></figure>

<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make config</span><br></pre></td></tr></table></figure>

<h2 id="内核的编译与安装"><a href="#内核的编译与安装" class="headerlink" title="内核的编译与安装"></a>内核的编译与安装</h2><p>内核与内核模块需要先编译</p>
<h3 id="编译内核及内核模块"><a href="#编译内核及内核模块" class="headerlink" title="编译内核及内核模块"></a>编译内核及内核模块</h3><p>使用make help可以查看所有可编译的参数</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">make vmlinux #未经压缩的内核</span><br><span class="line">make modules #仅内核模块</span><br><span class="line">make bzImange #经过压缩的内核（默认）</span><br><span class="line">make all #所有</span><br></pre></td></tr></table></figure>

<p>常见的在&#x2F;boot下的内核文件都是经过压缩后的，一般进行的操作：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">make -j 4 clean #清楚缓存文件，-j 4使用四个内核</span><br><span class="line">make -j 4 baImage #先编译内核</span><br><span class="line">make -j 4 modules #再编译模块</span><br><span class="line">make -j 4 clean bzImage modules</span><br></pre></td></tr></table></figure>

<h3 id="安装模块"><a href="#安装模块" class="headerlink" title="安装模块"></a>安装模块</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make modules_install</span><br></pre></td></tr></table></figure>

<h3 id="安装新内核与多重内核选项（grub）"><a href="#安装新内核与多重内核选项（grub）" class="headerlink" title="安装新内核与多重内核选项（grub）"></a>安装新内核与多重内核选项（grub）</h3><p>最好是保留旧内核，并设置多重引导，这样就算新内核编译错误了也可以正常开机</p>
<p>内核都放在<code>/usr/src/linux-headers-4.15.0-106/arch/boot/bzImage</code>文件夹下</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">cp /usr/src/linux-headers-4.15.0-106/arch/boot/bzImage /boot/vmlinuz-3.10.89new</span><br><span class="line">cp .config /boot/config-3.10.89new</span><br><span class="line">chmod a+x /boot/vmliuxz=3.10.89new</span><br><span class="line">cp System.map /boot/System.map-3.10.89new</span><br><span class="line">gzip -c Module.symvers &gt; /boot/symvers-3.10.89new.gz</span><br><span class="line">restorecon -Rv /boot</span><br></pre></td></tr></table></figure>

<ul>
<li><p>建立相对应的Initial Ram Disk（initrd）</p>
<p>一般如果系统使用SATA磁盘，支持SATA的驱动并没有直接编译到内核中，使用initramfs加载，使用如下方式建立initramfs，搭配正确的内核版本</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dracut -v /boot/initramfs-3.10.89new.img 3.10.89new</span><br></pre></td></tr></table></figure>
</li>
<li><p>编辑启动项（grub）</p>
</li>
<li><p>重新以新内核启动、测试、修改</p>
</li>
</ul>

        </div>

        
            <section class="post-copyright">
                
                    <p class="copyright-item">
                        <span>Author:</span>
                        <span>Ian Tang</span>
                    </p>
                
                
                    <p class="copyright-item">
                        <span>Permalink:</span>
                        <span><a href="https://tkhfree.github.io/2022/11/27/%E9%B8%9F%E5%93%A5%E7%9A%84%E7%A7%81%E6%88%BF%E8%8F%9C-2022-11-27/">https://tkhfree.github.io/2022/11/27/%E9%B8%9F%E5%93%A5%E7%9A%84%E7%A7%81%E6%88%BF%E8%8F%9C-2022-11-27/</a></span>
                    </p>
                
                
                    <p class="copyright-item">
                        <span>License:</span>
                        <span>Copyright (c) 2019 <a target="_blank" rel="noopener" href="http://creativecommons.org/licenses/by-nc/4.0/">CC-BY-NC-4.0</a> LICENSE</span>
                    </p>
                
                
                     <p class="copyright-item">
                         <span>Slogan:</span>
                         <span>Do you believe in <strong>DESTINY</strong>?</span>
                     </p>
                

            </section>
        
        <section class="post-tags">
            <div>
                <span>Tag(s):</span>
                <span class="tag">
                    
                    
                        <a href="/tags/c-c/"># c/c++</a>
                    
                        <a href="/tags/system/"># system</a>
                    
                        
                </span>
            </div>
            <div>
                <a href="javascript:window.history.back();">back</a>
                <span>· </span>
                <a href="/">home</a>
            </div>
        </section>
        <section class="post-nav">
            
                <a class="prev" rel="prev" href="/2022/11/27/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C-2022-11-27/">卷积神经网络</a>
            
            
            <a class="next" rel="next" href="/2022/11/27/SDN%E7%BD%91%E7%BB%9C%E7%AE%A1%E7%90%86%E6%8E%A5%E5%8F%A3P4Runtime-2022-11-27/">SDN网络管理接口P4Runtime</a>
            
        </section>


    </article>
</div>

            </div>
            <footer id="footer" class="footer">
    <div class="copyright">
        <span>© Ian Tang | Powered by <a href="https://hexo.io" target="_blank">Hexo</a> & <a href="https://github.com/Siricee/hexo-theme-Chic" target="_blank">Chic</a></span>
    </div>
</footer>

    </div>
</body>

</html>